﻿using Crap4Net;
using System;
using NUnit.Framework;
using Crap4Net.CCParsers;
using System.Collections.Generic;
using System.Linq;

namespace Crap4Net.UnitTests.CCParsersTests
{

    [TestFixture]
    public class VSMetricsParserTest
    {
        private const string VSMETRICS_FILE_PATH = @"UnitTestData\VSMetricsFiles\";
        
        [Test()]
        [ExpectedException(typeof(ApplicationException))]
        public void Data_FileNotLoaded_ThrowsException()
        {
            var target = new VSMetricsParser();
            var dummy = target.Data;
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void LoadData_InvalidFileName_throwsException()
        {
            var target = new VSMetricsParser();
            target.LoadData("NoSuchFile.xml");
        }

        [Test]
        public void Data_fileWithCtor_CtorDataIsParsedCorrectly()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");

            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", ".ctor", new string[] { }), 
                1 );
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_EmptyClass_CtorIsAdded()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "class2", ".ctor", new string[] { }),
                1);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_GenericMethod_CorrectNameIsParsed()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "GenericMethod<T>", new string[] { }),
                1);
            CollectionAssert.Contains(actual, expected);
        }



        [Test]
        public void Data_OverLoadedMethod_AllVariantsAreParsed()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var expected = new List<CCDataEntry>(){
                new CCDataEntry(
                    new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "method2", new string[] { }),
                    1),

                new CCDataEntry(
                    new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "method2", new string[] { "int" }),
                    1),
                new CCDataEntry(
                    new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "method2", new string[] { "double" }),
                    1),
                new CCDataEntry(
                    new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "method2", new string[] { "float" }),
                   1)
            };
            CollectionAssert.IsSubsetOf(expected,actual);
        }

        [Test]
        public void Data_Property_SetAndGetAreParsed()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var expectedGet = new CCDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "get_SomeProperty", new string[] { }),
                1);
            var expectedSet = new CCDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "set_SomeProperty", new string[] { "object" }),
                1);
            CollectionAssert.Contains(actual, expectedGet);
            CollectionAssert.Contains(actual, expectedSet);

        }

        [Test]
        public void Data_cctor_CorrectMaethodNameIsParsed()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", ".cctor", new string[] { }),
                1);
            CollectionAssert.Contains(actual, expected);

        }

        [Test]
        public void Data_StaticMethod_IsParsedCorrectly()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var expected = new CCDataEntry(
                new MethodSignature("DummyProject.dll", "dummyProject", "Class1", "staticMethod", new string[] { }),
                1);
            CollectionAssert.Contains(actual, expected);
        }

        [Test]
        public void Data_TypeWithoutNameSpace_IsParsedCorrectly()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var expected = new List<CCDataEntry>(){
                new CCDataEntry(
                    new MethodSignature("DummyProject.dll", "", "ClassWithNoNameSpace", ".ctor", new string[] { }),
                    1),
                new CCDataEntry(
                    new MethodSignature("DummyProject.dll", "", "ClassWithNoNameSpace", "StameMethod", new string[] { }),
                    1)
            };
            CollectionAssert.IsSubsetOf(expected, actual);
        }

        [Test]
        public void Data_TypeWithComplexNameSpace_IsParsedCorrectly()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var expected = new List<CCDataEntry>(){
                new CCDataEntry(
                    new MethodSignature("DummyProject.dll", "NameSpace1.NameSpace2", "ClassWithComplexNameSpace", ".ctor", new string[] { }),
                    1),
                new CCDataEntry(
                    new MethodSignature("DummyProject.dll", "NameSpace1.NameSpace2", "ClassWithComplexNameSpace", "StameMethod", new string[] { }),
                    1)
            };
            CollectionAssert.IsSubsetOf(expected, actual);
        }


        [Test]
        public void Data_WithClassConainingTwoCtorsAndCCtor_TwoCtorIsCreated()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var results = from entry in actual
                          where entry.Method.MethodName == ".ctor" && entry.Method.TypeName == "Class1"
                          select entry;

            Assert.AreEqual(2, results.Count());
        }

        [Test]
        public void Data_WithClassConainingctorAndCCtor_OnlyOneCCtorisCreated()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var results = from entry in actual
                          where entry.Method.MethodName == ".cctor" && entry.Method.TypeName == "Class1"
                          select entry;

            Assert.AreEqual(1, results.Count());

        }

        [Test]
        public void Data_WithClassConainingSeveralCtorsAndCCtor_OnlyOneCCtorIsCreated()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "DummyProjectMetrics.xml");
            var actual = target.Data;

            var results = from entry in actual
                          where entry.Method.MethodName == ".cctor" && entry.Method.TypeName == "Class1"
                          select entry;

            Assert.AreEqual(1, results.Count());
        }


        [Test]
        public void Data_problemwithcctor_onlyonecctorisParsed()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "CCtorIssue.xml");

            var actual = target.Data;
            var result = from entry in actual
                         where entry.Method.MethodName == ".cctor"
                         select entry;

            Assert.AreEqual(1,result.Count());
        }

        [Test]
        public void infrareport()
        {
            var target = new VSMetricsParser();
            target.LoadData(VSMETRICS_FILE_PATH + "FullInfraReport.xml");
            
            var actual = target.Data;
            var result = from entry in actual
                         where (entry.Method.TypeName=="Command" &&
                            entry.Method.Namespace == "Indigo.Infra.Icl.CommandExecuter")
                         select entry;

            Console.WriteLine(result.Count());


        }
    }
}
